图像拼接|OpenCV3.4 stitching源码分析(一)续
- 前言
- OpenCV与VLFeat的SIFT实现之对比
- 参考
前言
图像拼接|——OpenCV3.4 stitching模块分析(一)续
上一篇讲了OpenCV几种特征检测方法,其中默认的是surf算法,但个人感觉sift效果更好一些。实际上在很多计算机视觉项目中,特征检测更多使用的是vlfeat的sift实现,下面我们就来看看。
OpenCV与VLFeat的SIFT实现之对比
opencv
stitching模块中使用SiftFeaturesFinder类来进行sift特征检测,SiftFeaturesFinder类的构造函数如下:
SiftFeaturesFinder::SiftFeaturesFinder()
{
#ifdef HAVE_OPENCV_XFEATURES2DPtr<SIFT> sift_ &#61; SIFT::create();if( !sift_ )CV_Error( Error::StsNotImplemented, "OpenCV was built without SIFT support" );sift &#61; sift_;
#elseCV_Error( Error::StsNotImplemented, "OpenCV was built without SIFT support" );
#endif
}
find函数用来检测特征信息&#xff1a;
void SiftFeaturesFinder::find(InputArray image, ImageFeatures &features)
{UMat gray_image;CV_Assert((image.type() &#61;&#61; CV_8UC3) || (image.type() &#61;&#61; CV_8UC1));if(image.type() &#61;&#61; CV_8UC3){cvtColor(image, gray_image, COLOR_BGR2GRAY);}else{gray_image &#61; image.getUMat();}UMat descriptors;sift->detectAndCompute(gray_image, Mat(), features.keypoints, descriptors);features.descriptors &#61; descriptors.reshape(1, (int)features.keypoints.size());
}
可以看出&#xff0c;如果想直接使用SIFT检测特征&#xff0c;可以这么应用&#xff1a;
#include
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/xfeatures2d.hpp"using namespace cv;
using namespace cv::xfeatures2d;int main()
{Mat img &#61; imread("4.jpg");Mat gray_image;cvtColor(img, gray_image, COLOR_BGR2GRAY);Ptr<SIFT> sift &#61; SIFT::create();std::vector<KeyPoint> keypoints;Mat descriptors;sift->detectAndCompute(gray_image, Mat(), keypoints, descriptors);Mat output_img;drawKeypoints(img, keypoints, output_img, Scalar(255, 0, 0));std::cout << "Number of sift keypoints: " << keypoints.size() << std::endl;namedWindow("sift");imshow("sift", output_img);waitKey(0);return 0;
}
vlfeat
vlfeat是一个开源的轻量级的计算机视觉库&#xff0c;主要实现图像局部特征的提取和匹配以及一些常用的聚类算法。其对sift特征提取的各个步骤进行了封装&#xff0c;使用的方法如下&#xff1a;
- 调用vl_sift_new()初始化VlSiftFilt&#xff0c;设置sift提取时参数信息&#xff0c;如&#xff1a;图像的大小&#xff0c;Octave的个数&#xff0c;每个Octave的中的层数&#xff0c;起始的Octave的index。
- 设置剔除不稳定关键点的阈值。
- vl_sift_set_peak_thresh()设置接受极值点是一个关键点的最小对比度。该值越小&#xff0c;提取到的关键点就越多。
- vl_sift_set_edge_thresh()设置一个极值点是在边缘上的阈值。该值越小&#xff0c;提取到的关键点就越多。
这两个参数对最终提取到的特征点个数有很大的影响。 - 对尺度空间的每个Octave&#xff1a;
- 调用vl_sift_process_first_octave()和vl_sift_process_next_octave()来计算下一个DoG尺度空间&#xff08;返回VL_ERR_EOF时结束处理&#xff09;。
- 调用vl_sift_detect()进行关键点提取。
- 对每一个提取到的关键点&#xff1a;
· 调用vl_sift_calc_keypoint_orientations()计算关键点的方向&#xff0c;可能多于一个
· 对每个方向&#xff1a;
· 调用vl_sift_calc_keypoint_descriptor()计算每个方向的特征描述子。 - vl_sift_delete()释放资源。
完整代码&#xff1a;
#include
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "vlfeat-0.9.20/vl/sift.h"using namespace std;
using namespace cv;void vl_sift_extract(const Mat & grey_img,vector<VlSiftKeypoint> &kpts, vector<float*> &descriptors);int main()
{const string file &#61; "4.jpg";Mat img &#61; imread(file, IMREAD_GRAYSCALE);Mat color_img &#61; imread(file);vector<VlSiftKeypoint> kpts;vector<float*> descriptors;vl_sift_extract(img, kpts, descriptors);cout << kpts.size() << endl;for (int i &#61; 0; i < kpts.size(); i&#43;&#43;){
运行结果&#xff1a;
opencv sift | vlfeat sift |
opencv共检测出1287个特征点&#xff0c;vlfeat检测出1079个特征点。
似乎vlfeat检测出的特征点分布更加均匀&#xff1f;&#x1f602;&#x1f639;以上就是opencv与vlfeat的sift实现比较&#xff0c;如有问题希望一起交流。
参考
图像检索(1): 再论SIFT-基于vlfeat实现 - Brook_icv - 博客园